package com.wangsd.web.miniapp.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.wangsd.common.component.WeixinPayService;
import com.wangsd.common.utils.PayUtil;
import com.wangsd.web.face.entity.*;
import com.wangsd.web.face.service.*;
import com.wangsd.web.miniapp.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Autowired
    MerchantService merchantService;

    @Autowired
    MemberLevelService memberLevelService;

    @Autowired
    TOrderService tOrderService;

    @Autowired
    ServiceBusinessService serviceBusinessService;

    @Autowired
    AgentService agentService;

    @Autowired
    WeixinPayService wxPayServer;

    @Autowired
    MemberService memberService;

    @Autowired
    MemberAccountDetailService memberAccountDetailService;

    @Value("${service.url}")
    private String notifyUrl;

    @Override
    public Object wxPay(String miniAppId, String openid, Integer fee, HttpServletRequest request) throws Exception {
        /*调用微信支付*/
        WxPayUnifiedOrderRequest requestParam = new WxPayUnifiedOrderRequest();
        //商品名称
        requestParam.setBody("余额充值");
        //订单编号
        String orderNo = System.currentTimeMillis() + "";
        requestParam.setOutTradeNo(orderNo);
        //支付金额
        requestParam.setTotalFee(fee);
        //创建支付ip
        requestParam.setSpbillCreateIp(PayUtil.getIpAddr(request));
        //消息通知url
        requestParam.setNotifyUrl(this.notifyUrl + "/mini/wxNotify");
//        requestParam.setNotifyUrl("http://face.ngrok2.xiaomiqiu.cn/mini/wxNotify");
        requestParam.setTradeType("JSAPI");
        Merchant merchant = merchantService.selectByMiniAppId(miniAppId);
        Agent agent = agentService.getById(merchant.getAgentId());
        //ServiceBusiness serviceBusiness = serviceBusinessService.getById(agent.getBusinessId());

        //子商户id,需要通过productId从数据库product中查出来
        requestParam.setSubMchId(merchant.getSubMchId());
        requestParam.setSubOpenid(openid);
        requestParam.setSubAppId(miniAppId);

        Object object = wxPayServer.getService(agent.getBusinessId() + "", merchant.getSubMchId()).createOrder(requestParam);

        /*保存订单信息*/
        TOrder order = new TOrder();
        order.setMiniOpenId(openid);
        order.setOutTradeNo(orderNo);
        order.setOrderStatus(0);
        order.setOrderTotalFee(Long.valueOf(fee));
        order.setBusinessServiceId(agent.getBusinessId());
        order.setAgentId(agent.getId());
        order.setMerchantId(merchant.getId());
        tOrderService.save(order);
        return object;
    }

    @Override
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        BufferedOutputStream out = null;
        String resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        /*sb为微信返回的xml*/
        String notityXml = sb.toString();
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        String mchId = (String) map.get("mch_id");
        if ("SUCCESS".equals(returnCode)) {
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            ServiceBusiness serviceBusiness = serviceBusinessService.getOne(new QueryWrapper<ServiceBusiness>().eq("wx_mch_id", mchId));
            String sign = PayUtil.sign(validStr, serviceBusiness.getWxMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if (sign.equals(map.get("sign"))) {

                log.debug(JSON.toJSONString(map));

                String out_trade_no = (String) map.get("out_trade_no");

                String transaction_id = (String) map.get("transaction_id");

                String time_end = (String) map.get("time_end");

                Long cash_fee = Long.valueOf((String) map.get("cash_fee"));

                /*查询支付临时生成的订单*/
                TOrder orderSingle = tOrderService.selectByOutTradeNo(out_trade_no);
                if (orderSingle != null && orderSingle.getOrderStatus() == 0) {
                    Member member = memberService.selectByMiniOpenId(orderSingle.getMiniOpenId());
                    /*最后修改订单信息*/
                    TOrder sysOrder = new TOrder();
                    sysOrder.setTransactionId(transaction_id);
                    sysOrder.setRealPayFee(cash_fee);
                    sysOrder.setOrderStatus(1);
                    sysOrder.setId(orderSingle.getId());
                    sysOrder.setTimeEnd(time_end);
                    sysOrder.setTradeType("微信支付");
                    sysOrder.setPhone(member.getMobile());
                    tOrderService.updateById(sysOrder);

                    Long totalFee = orderSingle.getOrderTotalFee();


                    /*判断充值金额，达到多少金额，匹配合适的会员等级，若之前的会员等级更高，那么就不进行任何操作*/
                    Long memberLevelId = this.getMemberLevel(totalFee, orderSingle.getMerchantId(), member);

                    Member newMember = new Member();
                    newMember.setId(member.getId());
                    newMember.setTotalBalances(member.getTotalBalances() + orderSingle.getOrderTotalFee());
                    if (memberLevelId != null) {
                        newMember.setMemberLevelId(memberLevelId);
                    }
                    memberService.updateById(newMember);

                    /*充值记录新增，进行充值之后*/
                    MemberAccountDetail memberAccountDetail= new MemberAccountDetail();
                    memberAccountDetail.setMemberId(member.getId());
                    memberAccountDetail.setAmount(orderSingle.getOrderTotalFee());
                    /*余额增加*/
                    memberAccountDetail.setStatus(1);
                    /*余额变动*/
                    memberAccountDetail.setType(0);

                    BigDecimal bg = new BigDecimal( orderSingle.getOrderTotalFee() * 0.01);
                    DecimalFormat df1 = new DecimalFormat("0.00");
                    String str = df1.format(bg);
                    memberAccountDetail.setRemark("充值"+str+"元");
                    memberAccountDetailService.save(memberAccountDetail);
                }
            }
        } else {
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        /*响应给微信数据*/
        out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
    }

    /**
     * 获取会员等级id
     */
    private Long getMemberLevel(Long totalFee, Long merchantId, Member member) {
        /*当前会员等级*/
        if (member.getMemberLevelId() != null) {
            MemberLevel nowMemberLevel = memberLevelService.getById(member.getMemberLevelId());
            /*如果当前会员优惠(单次充值达标)比支付金额要多,那么就保持之前的优惠等级*/
            if (nowMemberLevel.getOnceFee() > totalFee) {
                return null;
            }
        }

        List<MemberLevel> memberLevelList = memberLevelService.list(new QueryWrapper<MemberLevel>()
                .eq("merchant_id", merchantId).orderByDesc("once_fee"));
        for (MemberLevel memberLevel : memberLevelList) {
            /*遍历，如果充值金额大于单次充值达标金额，那么就将当前等级id返回，修改当前会员的等级*/
            if (totalFee > memberLevel.getOnceFee()) {
                return memberLevel.getId();
            }
        }
        /*使用默认等级*/
        MemberLevel memberLevel = memberLevelList.get(memberLevelList.size() - 1);
        return memberLevel.getId();
    }
}
